package com.zg.system.auth;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zg.common.core.*;
import com.zg.common.core.dao.auth.*;
import com.zg.common.web.Req;
import com.zg.common.core.util.PwdUtil;
import com.zg.system.auth.domain.req.UserAndOrgListReq;
import com.zg.system.auth.domain.req.UserListReq;
import com.zg.system.auth.domain.req.UserPageReq;
import com.zg.system.auth.domain.vo.OrgVo;
import com.zg.system.auth.domain.vo.UserAndOrgVo;
import com.zg.system.auth.domain.vo.UserVo;
import com.zg.system.auth.vo.UserBatchVo;
import com.zg.system.auth.vo.UserInfoVo;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author Zxb
 */
@RestController
@RequiredArgsConstructor
public class UserController {
    private final AuthUserDao userDao;
    private final AuthMenuDao menuDao;
    private final AuthOrgDao orgDao;
    private final AuthRoleUserDao roleUserDao;
    private final AuthRoleMenuDao roleMenuDao;

    @GetMapping("/user/info")
    public R findUserInfo() {
        User user = Req.getCurrUser();
        AuthUser authUser = userDao.getOne(
                new LambdaQueryWrapper<AuthUser>()
                        .eq(AuthUser::getUsername, user.getUsername()));
        if (authUser == null) {
            return R.error("用户不存在");
        }
        return R.success(authUser);
    }

    @ApiOperation("分页查询用户")
    @PostMapping("/user/page")
    public R page(@RequestBody UserPageReq req) {
        IPage<AuthUser> pageParam = new Page<>(req.getPage(), req.getPageSize());
        LambdaQueryWrapper<AuthUser> queryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(req.getSearchStr())) {
            queryWrapper.like(AuthUser::getSearchStr, "%" + req.getSearchStr() + "%");
        }
        queryWrapper.eq(req.getOrgId() != null, AuthUser::getOrgId, req.getOrgId());
        queryWrapper.like(StrUtil.isNotBlank(req.getName()), AuthUser::getName, "%" + req.getName() + "%");
        queryWrapper.eq(StrUtil.isNotBlank(req.getSex()), AuthUser::getSex, req.getSex());
        IPage<AuthUser> result = userDao.page(pageParam, queryWrapper);
        return R.success(result);
    }

    @PostMapping("/user/add")
    public R add(@RequestBody @Valid AuthUser obj) {
        if (userDao.exists(
                new QueryWrapper<AuthUser>()
                        .lambda()
                        .eq(AuthUser::getUsername, obj.getUsername())
        )) {
            return R.error("用户名已经被使用");
        }
        if (userDao.exists(
                new QueryWrapper<AuthUser>()
                        .lambda()
                        .eq(AuthUser::getPhone, obj.getPhone())
        )) {
            return R.error("手机号已经被使用");
        }
        obj.setPassword(PwdUtil.generateDefaultPwd());
        obj.setNamePy(PinyinUtil.getPinyin(obj.getName()));
        obj.setIsTest(false);
        obj.setSearchStr(obj.getUsername() + obj.getName());
        userDao.save(obj);
        return R.success();
    }

    @PostMapping("/user/update")
    public R update(@RequestBody @Valid AuthUser obj) {
        AuthUser old = userDao.getById(obj.getId());
        A.isInDatabase(old, "用户");
        if (userDao.exists(
                new QueryWrapper<AuthUser>()
                        .lambda()
                        .eq(AuthUser::getUsername, obj.getUsername())
                        .ne(AuthUser::getId, old.getId())
        )) {
            return R.error("用户名已经被使用");
        }

        if (userDao.exists(
                new QueryWrapper<AuthUser>()
                        .lambda()
                        .eq(AuthUser::getPhone, obj.getPhone())
                        .ne(AuthUser::getId, old.getId())
        )) {
            return R.error("手机号已经被使用");
        }

        BeanUtil.copyProperties(obj, old, C.IGNORED_PROPERTIES);
        obj.setNamePy(PinyinUtil.getPinyin(obj.getName()));
        obj.setSearchStr(obj.getUsername() + obj.getName());
        userDao.updateById(old);
        return R.success();
    }

    @PostMapping("/user/del")
    public R del(@RequestBody List<Long> ids) {
        userDao.removeBatchByIds(ids);
        return R.success();
    }

    @PostMapping("/user/batch")
    @Transactional(rollbackFor = Exception.class)
    public R batch(@RequestBody UserBatchVo param) {
        List<Long> idList = param.getIds();
        for (Long id : idList) {
            AuthUser old = userDao.getById(id);
            if (old != null) {
                if (param.getIsPwdCk()) {
                    old.setPassword(param.getPwd());
                }
                if (param.getIsSexCk()) {
                    old.setSex(param.getSex());
                }
                if (param.getIsEduLevelCk()) {
                    old.setEduLevel(param.getEduLevel());
                }
                if (param.getIsOpenCk()) {
                    old.setIsOpen(param.getIsOpen());
                }
                userDao.updateById(old);
            }
        }
        return R.success();
    }

    @PostMapping("/user/save")
    public R save(@RequestBody @Valid UserInfoVo obj) {
        AuthUser old = userDao.getById(obj.getId());
        A.isInDatabase(old, "用户");
        BeanUtil.copyProperties(obj, old, C.IGNORED_PROPERTIES);
        old.setNamePy(PinyinUtil.getPinyin(old.getName()));
        old.setSearchStr(old.getUsername() + old.getName());
        userDao.updateById(old);
        return R.success();
    }

    @GetMapping("/user/menu")
    public R findOwnMenu() {
        List<AuthMenu> firstList = menuDao.list(
                new LambdaQueryWrapper<AuthMenu>()
                        .eq(AuthMenu::getLayer, 1)
                        .eq(AuthMenu::getIsUse, true)
        );
        firstList.stream().forEach(first -> {
            List<AuthMenu> secondList = menuDao.list(
                    new LambdaQueryWrapper<AuthMenu>()
                            .eq(AuthMenu::getPid, first.getId())
                            .eq(AuthMenu::getIsUse, true)
            );
            first.setChildren(secondList);
        });
        return R.success(firstList);
        /*User user = Req.getCurrUser();
        List<AuthRoleUser> authRoleUsers = roleUserDao.list(
                new LambdaQueryWrapper<AuthRoleUser>()
                        .eq(AuthRoleUser::getUserId, user.getId())
        );
        if (authRoleUsers.isEmpty()) {
            return R.success();
        }
        Set<Long> roleIds = authRoleUsers.stream().map(AuthRoleUser::getRoleId).collect(Collectors.toSet());
        List<AuthRoleMenu> authRoleMenus = roleMenuDao.list(
                new LambdaQueryWrapper<AuthRoleMenu>()
                        .in(AuthRoleMenu::getRoleId, roleIds)
        );
        if (authRoleMenus.isEmpty()) {
            return R.success();
        }
        Set<Long> menuIds = authRoleMenus.stream().map(AuthRoleMenu::getMenuId).collect(Collectors.toSet());
        List<AuthMenu> authMenus = menuDao.list(
                new LambdaQueryWrapper<AuthMenu>()
                        .eq(AuthMenu::getIsUse, true)
                        .in(AuthMenu::getId, menuIds)
        );
        if (authMenus.isEmpty()) {
            return R.success();
        }
        List<AuthMenu> tree = new ArrayList<>();
        Map<Long, AuthMenu> treeMap = new HashMap<>();
        for (AuthMenu authMenu : authMenus) {
            treeMap.put(authMenu.getId(), authMenu);
        }

        for (AuthMenu authMenu : authMenus) {
            Long pid = authMenu.getPid();
            if (pid == null) {
                tree.add(authMenu);
            } else {
                AuthMenu pAuthMenu = treeMap.get(pid);
                if (pAuthMenu != null) {
                    if (pAuthMenu.getChildren() == null) {
                        pAuthMenu.setChildren(new ArrayList<>());
                    }
                    pAuthMenu.getChildren().add(authMenu);
                } else {
                    tree.add(authMenu);
                }
            }
        }
        return R.success(tree);*/
    }

    @ApiOperation("查询用户")
    @PostMapping("/user/list")
    public R<List<UserVo>> list(@RequestBody UserListReq req) {
        LambdaQueryWrapper<AuthUser> queryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(req.getSearchStr())) {
            queryWrapper.like(AuthUser::getSearchStr, "%" + req.getSearchStr() + "%");
        }
        if (req.getUserIds() != null && req.getUserIds().size() > 0) {
            queryWrapper.in(AuthUser::getId, req.getUserIds());
        }
        List<AuthUser> list = userDao.list(queryWrapper);
        return R.success(BeanUtil.copyToList(list, UserVo.class));
    }

    @ApiOperation("查询用户和组织整合")
    @PostMapping("/user/listUserAndOrg")
    public R<UserAndOrgVo> listUserAndOrg(@RequestBody UserAndOrgListReq req) {
        LambdaQueryWrapper<AuthUser> userQueryWrapper = new LambdaQueryWrapper<>();
        LambdaQueryWrapper<AuthOrg> orgQueryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(req.getSearchStr())) {
            userQueryWrapper.like(AuthUser::getSearchStr,"%" + req.getSearchStr() + "%");
            orgQueryWrapper.like(AuthOrg::getSearchStr, "%" + req.getSearchStr() + "%");
        }
        if (req.getOrgId() != null) {
            userQueryWrapper.eq(AuthUser::getOrgId, req.getOrgId());
            orgQueryWrapper.eq(AuthOrg::getPid, req.getOrgId());
        } else {
            userQueryWrapper.isNull(AuthUser::getOrgId);
            orgQueryWrapper.isNull(AuthOrg::getPid);
        }
        List<AuthUser> userList = userDao.list(userQueryWrapper);
        List<AuthOrg> orgList = orgDao.list(orgQueryWrapper);
        UserAndOrgVo vo = new UserAndOrgVo();
        vo.setUserList(BeanUtil.copyToList(userList, UserVo.class));
        List<OrgVo> orgVoList = BeanUtil.copyToList(orgList, OrgVo.class);
        for (OrgVo orgVo : orgVoList) {
            long childCount = orgDao.count(
                    new LambdaQueryWrapper<AuthOrg>()
                            .eq(AuthOrg::getPid, orgVo.getId())
            );
            orgVo.setChildCount(childCount);
        }
        vo.setOrgList(orgVoList);
        return R.success(vo);
    }
}
